#!/user/bin/env python
# -*- coding:utf-8 -*-

import os
import select
import pty
import re
from subprocess import Popen
from collections import deque

class Active:
    # 参数说明：
    # cmd: 执行程序的命令
    # timeout： 等待超时时间，None 不设置超时。
    # buffsize: 每次读取字符的最大长度
    # maxlen： 最多读取的行数（超出后自动丢弃最前面的行）
    def __init__(self, cmd, timeout=None, buffsize=1024, maxlen=1024):
        self.timeout = timeout
        self.size = buffsize
        self.maxlen = maxlen
        self.io, slave = pty.openpty()
        self.popen = Popen(cmd, preexec_fn=os.setsid, stdin=slave, stdout=slave, stderr=slave, universal_newlines=True)
        os.close(slave)

    def __del__(self):
        if self.popen is not None:
            if self.popen.poll() is None:
                self.popen.kill()
            self.popen.wait()
            if self.io > 0:
                os.close(self.io)

    # 写入输入, 返回是否成功（结束请添加回车'\n'）
    def write(self, s):
        if self.popen.poll() is None:
            _, w, _ = select.select([], [self.io], [], self.timeout)
            if self.io in w:
                os.write(self.io, s)
                return True
        return False

    # 读取输出， 没有返回时会阻塞直到超时
    def read(self):
        if self.popen.poll() is None:
            r, _, _ = select.select([self.io], [], [], self.timeout)
            if self.io in r:
                return os.read(self.io, self.size)
        return ""

    # 读取输出， 正则匹配成功后返回读取到的所有字符， 无法匹配时会阻塞直到超时后返回。
    def expect(self, reg):
        res = ""
        exp = True
        queue = deque(maxlen=self.maxlen)
        pattern = re.compile(reg)
        while exp and self.popen.poll() is None:
            r, _, _ = select.select([self.io], [], [], self.timeout)
            if self.io in r:
                for line in os.read(self.io, self.size).splitlines(True):
                    queue.append(line)
                    if pattern.match(line):
                        exp=False
        while queue:
            res+=queue[0]
            queue.popleft()
        return res
        

